package com.ke.rule.base;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 功能部件规格清单
 * 
 * @author guyu
 */
public final class FuncUnitSpecBill {
  private String name;
  private String dtPath;
  private List<FuncUnitSpec> assemblyList;
  private List<Class<? extends IFuncUnit>> duplicateList;
  private List<Class<? extends IFuncUnit>> exclusionList;
  
  // 父清单
  private FuncUnitSpecBill parent;
  // 子列表(多个决策表的情况)
  private List<FuncUnitSpecBill> subBills;

  /**
   * constructor
   * @param name
   */
  public FuncUnitSpecBill(String name) {
    super();
    this.name = name;
    
    this.assemblyList = new ArrayList<>();
    this.duplicateList = new ArrayList<>();
    this.exclusionList = new ArrayList<>();
    
    this.parent = null;
    this.subBills = new ArrayList<>();
  }

  public String getName() {
    return name;
  }

  public String getDtPath() {
    return dtPath;
  }

  public void setDtPath(String dtPath) {
    this.dtPath = dtPath;
  }

  public List<FuncUnitSpec> getAssemblyList() {
    return assemblyList;
  }

  public List<Class<? extends IFuncUnit>> getDuplicateList() {
    return duplicateList;
  }

  public List<Class<? extends IFuncUnit>> getExclusionList() {
    return exclusionList;
  }

  public FuncUnitSpecBill getParent() {
    return parent;
  }

  public List<FuncUnitSpecBill> getSubBills() {
    return subBills;
  }

  @Override
  public String toString() {
    return "FuncUnitSpecBill [name=" + name + ", dtPath=" + dtPath + ", assemblyList="
        + assemblyList + ", duplicateList=" + duplicateList + ", exclusionList=" + exclusionList
        + ", parent=" + parent + ", subBills=" + subBills + "]";
  }

  /**
   * 增加子清单
   * @param bill
   */
  public void addSubBill(FuncUnitSpecBill bill) {
    this.subBills.add(bill);
    
    // 兄弟清单之间去重
    bill.assemblyList.forEach(spec -> {
      addToAssemblyList(spec);
    });
    // 兄弟清单之间不交叉排除，各自在自己的继承链路上排除
    this.exclusionList.addAll(bill.exclusionList);
  }
  
  /**
   * 增加子清单列表
   * @param bills
   */
  public void addSubBills(List<FuncUnitSpecBill> bills) {
    bills.forEach(b -> addSubBill(b));
  }
  
  /**
   * 从父类继承，当前清单须空
   * @param parent
   */
  public void inheritFrom(FuncUnitSpecBill parent) {
    if (!assemblyList.isEmpty() || !exclusionList.isEmpty()) {
      throw new UnsupportedOperationException("The list needs to be empty before inheritance");
    }
    
    if (null != this.parent) {
      throw new IllegalArgumentException("Multiple inheritance is not supported");
    }
    if (Objects.equals(this.parent, parent)) {
      return;
    }
    this.parent = parent;
    
    // 父列表加入到当前列表
    this.assemblyList.addAll(parent.assemblyList);
    this.duplicateList.addAll(parent.duplicateList);
    this.exclusionList.addAll(parent.exclusionList);
  }
  
  /**
   * 增加到装配表
   * @param spec
   */
  public void addToAssemblyList(FuncUnitSpec spec) {
    // 去重
    // 1、子类override父类属性，删除已有父类部件 2、同级兄弟决策表，以后来者为准，删除前序规格
    // 综上两种情况，都以后入者为准
    boolean removed = assemblyList.removeIf(u -> u.equals(spec));
    if (removed) {
      this.duplicateList.add(spec.getKlazz());
    }
    // 添加
    assemblyList.add(spec);
  }
  
  /**
   * 继承排除
   * @param exclusionList
   */
  public void addToExclusionList(List<Class<? extends IFuncUnit>> exclusionList) {
    this.exclusionList.addAll(exclusionList);
    exclusionList.forEach(excl -> {
      assemblyList.removeIf(x -> x.getKlazz().equals(excl));
    });
  }
  
  /**
   * 清单是否为空?
   * @return
   */
  public boolean isEmpty() {
    return this.assemblyList.isEmpty();
  }
  
  /**
   * 清除清单内容
   * @return
   */
  public void clear() {
    this.assemblyList.clear();
    this.duplicateList.clear();
    this.exclusionList.clear();
    
    if (null != this.parent) {
      this.parent.clear();
    }
    this.subBills.forEach(bill -> bill.clear());
  }
  
  /**
   * 对待装配执行的功能部件进行排序(按优先级序号排序，空的排在后面)
   */
  public void orderByPriority() {
    if (isEmpty()) {
      return;
    }
    assemblyList = FuncUnitSpec.distinctAndOrder(assemblyList);
  }
}
